package LawsonTransformJava.dao;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.TreeMap;

import LawsonTransformJava.pgm.Report;

public class DAObject {

	static TreeMap<String, TreeMap<String, Method>> CLASSMAP = new TreeMap<String, TreeMap<String, Method>>();
	
	static final String DEFAULT_SEPARATOR = ",";
	
	private static final String DBTYPE = System.getenv("DBTYPE");
	private static final boolean DEBUG = "true".equalsIgnoreCase(System.getenv("DEBUG"));

	// @ TODO CLIENTSPECIFIC - Change DAO reference depending on data input
	static final String DAODBTYPE = "MSA";
	//static final String DAODB = "ORA";
	
	protected DAODB data = null;
	protected DAOFactoryAccessDB xref = null;

	protected ResultSet rslt = null;
	protected ResultSetMetaData rsmd = null;
	protected ResultSet countRecs = null;

	protected Statement stmtData = null;
	protected Connection connData = null;
	protected Statement countStmtData = null;
	protected String sqlData = null;

	protected SimpleDateFormat df = new SimpleDateFormat("");
	protected boolean hasMoreRecs = true;
	protected int recCount = 0;
	protected String whereClause = "";
	protected FileWriter output = null;
	protected FileWriter output2 = null;
	protected File outputFile = null;
	protected File outputFile2 = null;
	protected FileWriter errOutput = null;
	protected File errOutputFile = null;	
	protected Report errReport = null;
	protected String strSQLValue = null;
	protected String strMethodName = null;
	protected int columnCount = 0;
	protected Method aMthd = null;
	protected TreeMap<String, Method> lstMthds = new TreeMap<String, Method>();

	 public Object createObject(ResultSet rslt, Object obj) throws SQLException, InvocationTargetException, IllegalAccessException,
		IllegalArgumentException {
		 Method[] mthds = null;
		//Check the Map of classes and methods to see if we've already created this list from another object call
		if(CLASSMAP.containsKey(obj.getClass().getName())) {
			lstMthds = CLASSMAP.get(obj.getClass().getName());
		} else {
			//Populate an array of all the "methods" for this obj
			mthds = obj.getClass().getMethods();
			//Add all the methods to the TreeMap with the method name (getName()) as the key value - UPPERCASE
			for (int i=0;i<mthds.length;i++){
				lstMthds.put(mthds[i].getName().toUpperCase(), mthds[i]);
			}
			//Add this objects methods to the Map for further use
			CLASSMAP.put(obj.getClass().getName(), lstMthds);
		}
		
//		String strSQLValue, strMethodName = null;
		columnCount = rsmd.getColumnCount();
		
		if (DBTYPE.equalsIgnoreCase("ORA")) {
			populateORAData(obj);
		} else if (DBTYPE.equalsIgnoreCase("MSA")) {
			populateMSAData(obj);
		} else {
			System.err.println("Environment Variable not set: DBTYPE=ORA|MSA");
		}

		strSQLValue = null;
		strMethodName = null;
		
		//Return the object that was passed in but with the values "set"
		return obj;
}

	public void setWhereClause(String where) {
		this.whereClause = where.trim();
	}
	
	public void setSQLData() {
		this.sqlData = this.sqlData + this.whereClause;
	}

	private void populateORAData(Object obj) throws SQLException, InvocationTargetException, IllegalAccessException {
		for(int i=0;i<columnCount;i++) {
			//Check ColumnTypeName for Type - CHAR
			if (rsmd.getColumnTypeName(i+1).equalsIgnoreCase("CHAR")) {
						if ((strSQLValue=rslt.getString(i+1))!=null) {
							strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
							aMthd = (Method)lstMthds.get(strMethodName);
							if(aMthd!=null)
								aMthd.invoke(obj,strSQLValue.trim());
							else
								//Send this to the err output for debugging
								System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
						}
			}
			//Check ColumnTypeName for Type - NUMBER (no decimals;getScale=0)
			else if(rsmd.getColumnTypeName(i+1).equalsIgnoreCase("NUMBER"))
				if(rsmd.getScale(i+1)==0) {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getInt(i+1));
					else
						//Send this to the err output for debugging
						System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
				//Check ColumnTypeName for Type - DECIMAL
				else {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getFloat(i+1));
					else
						//Send this to the err output for debugging
						System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
			//Check ColumnTypeName for Type - DATE
			else if(rsmd.getColumnTypeName(i+1).equalsIgnoreCase("DATE"))
				if(rsmd.getScale(i+1)==0) {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getDate(i+1));
					else
						//Send this to the err output for debugging
						System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
		}
	}
	
	private void populateMSAData(Object obj) throws SQLException, InvocationTargetException, IllegalAccessException {
		for(int i=0;i<columnCount;i++) {
			if (DEBUG) {
				System.out.print(rsmd.getColumnName(i+1).toUpperCase() + "\t");
				System.out.println(rsmd.getColumnTypeName(i+1));
			}
			//Check ColumnTypeName for Type - CHAR
			if (rsmd.getColumnTypeName(i+1).equalsIgnoreCase("VARCHAR")) {
				if ((strSQLValue=rslt.getString(i+1))!=null) {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj,strSQLValue.trim());
					else
						//Send this to the err output for debugging
						if (DEBUG)
							System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
			}
			//Check ColumnTypeName for Type - NUMBER (no decimals;getScale=0)
			else if(rsmd.getColumnTypeName(i+1).equalsIgnoreCase("INTEGER") || rsmd.getColumnTypeName(i+1).equalsIgnoreCase("CURRENCY")
					|| rsmd.getColumnTypeName(i+1).equalsIgnoreCase("DOUBLE"))
				if(rsmd.getScale(i+1)==0) {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getInt(i+1));
					else
						//Send this to the err output for debugging
						if (DEBUG)
							System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
				//Check ColumnTypeName for Type - CURRENCY
				else {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getFloat(i+1));
					else
						//Send this to the err output for debugging
						if (DEBUG)
							System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
			//Check ColumnTypeName for Type - DATETIME
			else if(rsmd.getColumnTypeName(i+1).equalsIgnoreCase("DATETIME"))
				if(rsmd.getScale(i+1)==0) {
					strMethodName = "SET" + rsmd.getColumnName(i+1).toUpperCase();
					aMthd = (Method)lstMthds.get(strMethodName);
					if(aMthd!=null)
						aMthd.invoke(obj, rslt.getDate(i+1));
					else
						//Send this to the err output for debugging
						if (DEBUG)
							System.err.println("Method not found - " + obj.getClass().getName() + "." + strMethodName);
				}
		}
	}
}
